package ncsutest;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

import ncsutest.monitors.LEDCalibrationMonitor;
import ncsutest.monitors.LEDTestMonitor2;
import ncsutest.robowulf.RobowulfCalibration;
import ncsutest.robowulf.RobowulfTests;
import ncsutest.util.LEDs;
import ncsutest.util.Switches;

import com.sun.spot.peripheral.Spot;
import com.sun.spot.resources.transducers.LEDColor;
import com.sun.spot.testFramework.ITestCases;
import com.sun.spot.testFramework.SystemOutTestResultLog;
import com.sun.spot.testFramework.TestRunner;
import com.sun.spot.util.Utils;

public class NCSUTestController extends MIDlet {
	private static final String LAST_SUITE_PROPERTY = "SpotJUnit.lastTestSuite";

	private static final ITestCases[] TEST_CASES = {
		new RobowulfTests(new int[] {0}), 				// One sonar
		new RobowulfTests(new int[] {1,2,3}), 			// Three sonars
		new RobowulfTests(new int[] {4,5,6,7}), 		// IR sensors
		new RobowulfTests(new int[] {0,4,5,6,7}), 		// IR sensors, one sonar
		new RobowulfTests(new int[] {1,2,3,4,5,6,7})	// IR sensors, three sonars
		};
	
	private static final NCSUCalibrationBase[] CALIBRATIONS = {
		new RobowulfCalibration(new int[] {}),
		new RobowulfCalibration(new int[] {}),
		new RobowulfCalibration(new int[] {0,1}),
		new RobowulfCalibration(new int[] {0,1}),
		new RobowulfCalibration(new int[] {0,1})
	};
	
    private Switches switches = Switches.getSwitches();
	private int testSuite;
    
    protected void startApp() throws MIDletStateChangeException {
    	System.out.println("Hello world!");

		NCSUTestMonitor testMonitor = new LEDTestMonitor2(new SystemOutTestResultLog());
    	System.out.println("Monitor set up");
		testSuite = loadLastTestSuite();
    	while (true) {
    		LEDs.clearLEDs();

    		testSuite = selectTestSuite(testSuite);
    		
    		LEDs.clearLEDs();
    		    		
    		try {
    			doCalibration(testSuite);
    		} catch (Exception e) {
    			e.printStackTrace();
    			NCSUTestController.unexpectedErrorOccured();
    		}
    		
    		LEDs.clearLEDs();

    		ITestCases testBase = createTestCases(testSuite);
    		testMonitor.setTestCases(testBase);

    		TestRunner runner = new TestRunner(testMonitor);
    		runner.run(testBase);
    		Utils.sleep(500L);
    		
    		LEDs.clearLEDs();
    		
    		//switches.waitForSwitchRelease();
    		displayResults(testMonitor);
    	}
    }
  
    private void displayResults(NCSUTestMonitor monitor) {
    	int input;
    	int testNum = 0;
    	while (true) {
    		
    		int result = monitor.getResultOfTest(testNum);

    		LEDColor color = null;
    		
    		switch (result) {
    		case NCSUTestMonitor.SUCCESS:
    			color = LEDColor.GREEN;
    			break;
    		case NCSUTestMonitor.FAILURE:
    			color = LEDColor.RED;
    			break;
    		case NCSUTestMonitor.ERROR:
    		default:
    			color = LEDColor.YELLOW;
    			break;
    		}		

    		LEDs.displayBinaryNumber(color, testNum+1, 7);

    		input = switches.waitForSwitchRelease();
    		switch (input) {
    		case Switches.BOTH:
    			return;
    		case Switches.LEFT:
        		if (testNum > 0) testNum--;
    			break;
    		case Switches.RIGHT:
        		if (testNum < monitor.getNumTests() - 1) testNum++;
    			break;
    		}
    	}
	}

	private ITestCases createTestCases(int testSuite) {
		return TEST_CASES[testSuite];
	}
	
	private int selectTestSuite(int suite) {
    	System.out.println("Selecting suite");
    	while (true) {
        	System.out.println("Displaying " + (suite+1));
			LEDs.displayBinaryNumber(LEDColor.BLUE, suite+1, 7);
			int input = switches.waitForSwitchRelease();
			
			if (input == Switches.BOTH) break;
			if (input == Switches.LEFT && suite > 0) suite--;
			if (input == Switches.RIGHT && suite < TEST_CASES.length - 1) suite++;
		}

		return suite;
	}

	private void doCalibration(int testSuite) throws Exception {
		NCSUCalibrationBase calib = CALIBRATIONS[testSuite];

		NCSUCalibrationMonitor monitor = new LEDCalibrationMonitor(calib);
		NCSUCalibrationRunner runner = new NCSUCalibrationRunner(monitor);
		runner.run(calib);
	}
	
	private int loadLastTestSuite() {
		String testSuiteStr = System.getProperty(LAST_SUITE_PROPERTY);
		if (testSuiteStr == null) return 0;
		else {
			try {
				return Integer.parseInt(testSuiteStr);
			} catch (NumberFormatException nfe) {
				return 0;
			}
		}
	}
	
	protected void pauseApp() {}
    
    protected void destroyApp(boolean arg) throws MIDletStateChangeException {
    	Spot.getInstance().setPersistentProperty(LAST_SUITE_PROPERTY, Integer.toString(testSuite));
    }

    
    public static void unexpectedErrorOccured() {
		while (true) {
			LEDs.setLEDs(0, 7, LEDColor.RED);
			Utils.sleep(500);
			LEDs.clearLEDs();
			Utils.sleep(500);
		}
    }
}
